﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Scheduler.Business_Logic_Layer
{
    /**Class Business_Logic_Layer.StaffingRequirements
     * @author Sara Tuohy
     * @version 1.0
     * @written March, 2012
     * Read staffing info and saves to global table for single point of access 
     */ 
    class StaffingRequirements
    {
        /**
         * Table adapter to access DB                   */ 
        private Data_Access_Layer.StaffingRequirements staffReqData;
        /**
         * Holds days of schedule data                  */ 
        private OperationDay[] operationWeek;
        /**
         * Constant for loop control                    */ 
        private const int NUM_WEEK_DAYS = 7;
        /**
         * Day format for DB                            */ 
        private string[] weekDays = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
        /**
        * Company ID is table key                       */ 
        private string Co_ID = Presentation_Layer.GlobalVariables.GlobalCompanyID;
        /**
         * An array for translating between open hours and 48 half hour all day time slots          */ 
        private String[] allTimeSlots;  
                                     //=  { " ",  "00:00", "00:30", "01:00", "01:30", "02:00", "02:30", 
                                     //           "03:00", "03:30", "04:00", "04:30", "05:00", "05:30", 
                                     //           "06:00", "06:30", "07:00", "07:30", "08:00", "08:30", 
                                     //           "09:00", "09:30", "10:00", "10:30", "11:00", "11:30",
                                     //           "12:00", "12:30", "13:00", "13:30", "14:00", "14:30",
                                     //           "15:00", "15:30", "16:00", "16:30", "17:00", "17:30",
                                     //           "18:00", "18:30", "19:00", "19:30", "20:00", "20:30", 
                                     //           "21:00", "21:30", "22:00", "22:30", "23:00", "23:30"};
        
        /**Method: StaffingRequirements
         * Constructor
         */ 
        public StaffingRequirements()
        {
            operationWeek = new OperationDay[NUM_WEEK_DAYS];
            allTimeSlots = Presentation_Layer.GlobalVariables.GlobalAllTimeSlots;
            loadDBData();
        }

        /**Method: loadDBData
         * Reads the DB and stores info in Globals
         */ 
        public void loadDBData()
        {   //Set payroll
            staffReqData = new Data_Access_Layer.StaffingRequirements("Sunday", Co_ID);
            if (staffReqData.locateCompany())
            {
                decimal weeklyPayroll = staffReqData.getMaxWeeklyPayroll();
                Presentation_Layer.GlobalVariables.GlobalCompanyMaxWeeklyPayroll = weeklyPayroll;
            }
            //Had to break into two for loops due to a problem ...
            //This loop allocates the operation days and buildes the operation week
            for (int i = 0; i < NUM_WEEK_DAYS; i++)
            {
                staffReqData = new Data_Access_Layer.StaffingRequirements(weekDays[i], Co_ID);
                setStartEndTimes(staffReqData, i);
            }
            //This loop determines the ranges to be staffed to updates the operation days 
            for (int i = 0; i < NUM_WEEK_DAYS; i++)
            {
                staffReqData = new Data_Access_Layer.StaffingRequirements(weekDays[i], Co_ID);
                if (operationWeek[i].isOpen())
                {
                    setStaffRequiredFromDB(staffReqData, i);
                }
            }
            Scheduler.Presentation_Layer.GlobalVariables.GlobalOperationWeek = operationWeek;
            Scheduler.Presentation_Layer.GlobalVariables.GlobalHoursOfOperationSet = true;
        }

        /**Method setStartEndTimes
         * sets the start and end times for given day
         * @param StaffingRequirements DB access
         * @param int dayIdx index of day to update
         */ 
        private void setStartEndTimes(Data_Access_Layer.StaffingRequirements srd, int dayIdx)
        {
            Data_Access_Layer.StaffingRequirements staffRequirementsData = srd;
            string strStart, strEnd;

            if (staffRequirementsData.locateOperatingDay())
            {
                if (!staffReqData.getIsClosed())
                {
                    strStart = staffRequirementsData.getStartTime().ToString();
                    strEnd = staffRequirementsData.getEndTime().ToString();
                    strStart = strStart.Substring(0, 5);        //change "10:30:00" to "10:30"
                    strEnd = strEnd.Substring(0, 5);                                
                    operationWeek[dayIdx] = new OperationDay(weekDays[dayIdx], strStart, strEnd,
                        Array.IndexOf(allTimeSlots, strStart), Array.IndexOf(allTimeSlots, strEnd));                    
                }                       //end if !closed
                else
                {
                    operationWeek[dayIdx] = new OperationDay(weekDays[dayIdx], "00:00", "00:00", -1, -1);
                }                       //end else closed day
            }                           //end if day located
            else
            {
                //should never, ever, EVER happen ...
                MessageBox.Show("Locate failed for " + weekDays[dayIdx]);
            }     
        }


        /**Method: setStaffRequiredFromDB
         * Reads the number needed per time slot and updates the operation day
         * @param table adapter srd, to read the staffrequirements table
         * @param int dayIdx index of day
         */ 
        private void setStaffRequiredFromDB(Data_Access_Layer.StaffingRequirements srd, int dayIdx)
        {
            Array numStaffRequiredFromDB;
            object[] objArray = new object[49];
            int[] numReqPerAllTimeSlots = new int[48];
            Data_Access_Layer.StaffingRequirements staffRequirementsData = srd;

            if (staffRequirementsData.locateStaffingRequirements())
            {
                bool conversionFailed = false;
                numStaffRequiredFromDB = staffRequirementsData.getAllPerHr();
                numStaffRequiredFromDB.CopyTo(objArray, 0);

                for (int i = 0; i < numReqPerAllTimeSlots.Length; i++)
                {
                    try
                    {
                        int num = Convert.ToInt32(objArray[i + 1].ToString());
                        numReqPerAllTimeSlots[i] = num;
                    }
                    catch
                    {
                        int idx = i + 1;
                        MessageBox.Show("Conversion failed for " + objArray[0].ToString() +
                            " object number " + idx + " is: " + objArray[i + 1].ToString(),
                            "Conversion Failure on Staff Requirements from DB", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        conversionFailed = true;
                    }
                }
                if (!conversionFailed)
                {                 
                    operationWeek[dayIdx].setNumPerAllTimeSlots(numReqPerAllTimeSlots);
                    operationWeek[dayIdx].copyToOpenTimeSlots();
                    //setEmpNums[dayIdx].Enabled = true;
                }

            }                           //end if day located
            else MessageBox.Show("Locate failed for Staffing Requirements for " + weekDays[dayIdx]);
        }
    }
}
